"""
编写关于学生信息的类，实例属性包括：学号、姓名、性别，班级、
n 门课程成绩，要求：
1) 利用文件读取，创建一个包含 n 个学生的班级;
文件存储格式以空格分隔例如： 202001 李四 1 班 高数:89 英语:28 计算机:77
2) n 门课程成绩利用字典存储，支持成绩录入、修改与删除;
3) 求解每个学生的 n 门成绩的平均值，及其平均值排名。并按照成绩平均成绩
排名正序输出：学号、姓名、性别、n 门课程成绩，n 门课程平均值，排名。
"""


class Students:
    def __init__(self, stunumber, name, sex, classroom, grade):
        self.stunum = stunumber
        self.stuname = name
        self.stusex = sex
        self.stuclassroom = classroom
        self.stugrade = grade
        self.stuavgergrade = self.getavgergrade()

    def getname(self):
        return self.stuname

    def getnum(self):
        return self.stunum

    def changegrade(self, subject, lastgrade):
        self.stugrade[subject] = lastgrade

    def addgrade(self, subject, lastgrade):
        self.stugrade[subject] = lastgrade

    def removegrade(self, subject):
        self.stugrade.pop(subject)

    def getavgergrade(self):
        sum = 0
        num = 0
        for key in self.stugrade:
            sum += self.stugrade[key]
            num += 1
        return sum / num

    def show(self):
        print("学号:", self.stunum, "姓名：", self.stuname, "性别:", self.stusex, "班级：", self.stuclassroom, end="")
        for key, item in self.stugrade.items():
            # 格式化字符串的函数 str.format() ^, <, > 分别是居中、左对齐、右对齐，后面带宽度
            print("{0:>5}{1}{2:<5}".format(key, "=", item), end="")
        # 指定小数精度 %m.nf m 表示最小宽度，n 表示输出精度，.是必须存在的。
        print("平均成绩：", "%4.2f" % self.getavgergrade(), end="")


stulist = []


# 利用文件读取，创建一个包含 n 个学生的班级;
def creatstulist():
    f = open("stulist.txt", 'r', encoding='utf-8')
    while True:
        buf = f.readline()
        if buf:
            stuinfo = buf.split(" ")
            stugradelist = {}
            for i in range(4, len(stuinfo)):
                stugradeinfo = stuinfo[i].split(":")
                stugradelist[stugradeinfo[0]] = eval(stugradeinfo[1])
            tempstudent = Students(stuinfo[0], stuinfo[1], stuinfo[2], stuinfo[3], stugradelist)
            stulist.append(tempstudent)
        else:
            break
    f.close()


def addstudent():
    fwrite = open("stulist.txt", "a", encoding="utf-8")
    # "学号:", self.stunum, "姓名：", self.stuname, "性别:", self.stusex, "班级：", self.stuclassroom,end = ""
    stunum = input("请输入学生学号：")
    stuname = input("请输入学生姓名：")
    stusex = input("请输入学生性别")
    stuclass = input("请输入学生班级")
    fwrite.write(stunum + " " + stuname + " " + stusex + " " + stuclass)
    stugradenum = eval(input("请输入要录入的成绩的门数："))
    stugradelist = {}
    for i in range(stugradenum):
        stucrouse = input("请输入科目：")
        stugrad = input(f"请输入{stucrouse}的分数：")
        fwrite.write(" " + stucrouse + ":" + stugrad)
        stugradelist[stucrouse] = eval(stugrad)
    fwrite.write('\n')
    tempstudent = Students(stunum, stuname, stusex, stuclass, stugradelist)
    stulist.append(tempstudent)
    fwrite.close()


# 成绩修改
def stugradechange(name, subject, score):
    for i in stulist:
        if i.getname() == name:
            i.changegrade(subject, score)


# 成绩删除
def stugradepop(name, subject):
    for i in stulist:
        if i.getname() == name:
            i.removegrade(subject)


# 成绩录入
def stugradeadd(name, subject, score):
    for i in stulist:
        if i.getname() == name:
            i.addgrade(subject, score)


def showstulist():
    stulist.sort(key=lambda x: x.getavgergrade(), reverse=True)
    for key, item in enumerate(stulist):
        item.show()
        print("排名：", key + 1)


creatstulist()
while True:
    print("1：学生成绩录入")
    print("2：学生成绩修改")
    print("3：学生成绩删除")
    print("4：学生成绩展示")
    print("5：添加学生")
    print("6：———退出———")
    i = eval(input("请输入要执行的操作"))
    if i == 2:
        name = input("请输入要修改的姓名")
        subject = input("请输入要修改的科目")
        score = eval(input("请输入要修改的分数"))
        stugradechange(name, subject, score)
    elif i == 1:
        name = input("请输入要录入的姓名")
        subject = eval(input("请输入要录入的科目"))
        score = input("请输入要录入的分数")
        stugradeadd(name, subject, score)
    elif i == 3:
        name = input("请输入要删除的姓名")
        subject = input("请输入要删除的科目")
        stugradepop(name, subject)
    elif i == 4:
        showstulist()
    elif i == 5:
        addstudent()
    elif i == 6:
        break
